package yxy.game.pm2.module.therionHunting;

import org.apache.commons.lang3.ArrayUtils;
import org.joda.time.DateTime;
import yxy.apple.util.ActiveUtil;
import yxy.apple.util.concurrent.ThreadPoolManager;
import yxy.cherry.battle.Team;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.therionboss;
import yxy.cherry.data.bean.theriondate;
import yxy.cherry.data.bean.therionrankreward;
import yxy.cherry.data.string.GameString;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.Format;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.area.AreaBean;
import yxy.game.pm2.bean.area.AreaGroupBean;
import yxy.game.pm2.bean.currency.Currencies;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.bean.module.rank.RankModule;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.bean.task.TaskType;
import yxy.game.pm2.message.BattleMessage;
import yxy.game.pm2.message.PlayerMessage;
import yxy.game.pm2.message.TherionHuntingMessage;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.NotificationHandle;
import yxy.game.pm2.module.battle.*;
import yxy.game.pm2.module.mail.MailHandle;
import yxy.game.pm2.module.mail.MailTypeEnum;
import yxy.game.pm2.module.player.PlayerHandle;
import yxy.game.pm2.module.task.TaskHandle;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wrs
 * @name TherionHandle
 * @description
 * @since 2022-06-09
 */
public class TherionHandle {

    /**
     * 神兽玩法  神兽模型初始化
     *
     * @param therionModule
     * @param therionboss
     * @param type
     */
    public void therionModuleInit(TherionModule therionModule, therionboss therionboss, int type, Map<Integer, TherionModule> map) {
        int code = therionboss.getId() % 4;
        therionModule.setGemeType(type); //玩法类型
        if (type == TherionModule.THERION_LOCAL) { //本服
            if (code == 1 && therionboss.getType() == type) {
                therionModule.setTherionType(TherionModule.TSINGLUNG);
                therionModule.setId(therionboss.getId());
                therionModule.setName(therionboss.getName());
                therionModule.setLife(therionboss.getLife());
                therionModule.setTotalLife(therionboss.getLife());
                therionModule.setStatus(2); //已重生
                therionModule.setChallengeNum(0); //初始挑战人数为0
                therionModule.setRebirthtime(therionboss.getRebirthtime()); //刷新时长
                therionModule.setResurrectTime(null); //重生倒计时时间  死亡时间 + 复活冷却时间  初始值为空

                TherionModelInfo therionModelInfo = TherionModelInfo.get(TherionModule.TSINGLUNG);
                therionModule.setConditions(therionModelInfo.getCondition()); //关卡开放时间

                map.put(TherionModule.TSINGLUNG, therionModule); //青龙
            }
            if (code == 2 && therionboss.getType() == type) {
                therionModule.setTherionType(TherionModule.WHITETIGER);
                therionModule.setId(therionboss.getId());
                therionModule.setName(therionboss.getName());
                therionModule.setLife(therionboss.getLife());
                therionModule.setTotalLife(therionboss.getLife());
                therionModule.setStatus(2); //已重生
                therionModule.setChallengeNum(0); //初始挑战人数为0
                therionModule.setRebirthtime(therionboss.getRebirthtime()); //刷新时长
                therionModule.setResurrectTime(null); //重生倒计时时间  死亡时间 + 复活冷却时间  初始值为空

                TherionModelInfo therionModelInfo = TherionModelInfo.get(TherionModule.WHITETIGER);
                therionModule.setConditions(therionModelInfo.getCondition()); //关卡开放时间

                map.put(TherionModule.WHITETIGER, therionModule); //白虎
            }
            if (code == 3 && therionboss.getType() == type) {
                therionModule.setTherionType(TherionModule.ROSEFINCH);
                therionModule.setId(therionboss.getId());
                therionModule.setName(therionboss.getName());
                therionModule.setLife(therionboss.getLife());
                therionModule.setTotalLife(therionboss.getLife());
                therionModule.setStatus(2); //已重生
                therionModule.setChallengeNum(0); //初始挑战人数为0
                therionModule.setRebirthtime(therionboss.getRebirthtime()); //刷新时长
                therionModule.setResurrectTime(null); //重生倒计时时间  死亡时间 + 复活冷却时间  初始值为空

                TherionModelInfo therionModelInfo = TherionModelInfo.get(TherionModule.ROSEFINCH);
                therionModule.setConditions(therionModelInfo.getCondition()); //关卡开放时间

                map.put(TherionModule.ROSEFINCH, therionModule); //朱雀
            }
            if (code == 0 && therionboss.getType() == type) {
                therionModule.setTherionType(TherionModule.BASALTIC);
                therionModule.setId(therionboss.getId());
                therionModule.setName(therionboss.getName());
                therionModule.setLife(therionboss.getLife());
                therionModule.setTotalLife(therionboss.getLife());
                therionModule.setStatus(2); //已重生
                therionModule.setChallengeNum(0); //初始挑战人数为0
                therionModule.setRebirthtime(therionboss.getRebirthtime()); //刷新时长
                therionModule.setResurrectTime(null); //重生倒计时时间  死亡时间 + 复活冷却时间  初始值为空

                TherionModelInfo therionModelInfo = TherionModelInfo.get(TherionModule.BASALTIC);
                therionModule.setConditions(therionModelInfo.getCondition()); //关卡开放时间

                map.put(TherionModule.BASALTIC, therionModule); //玄武
            }
        } else { //跨服、世界
            TherionModelInfo therionModelInfo = TherionModelInfo.get(type);
            if (code == 1 && therionboss.getType() == type) {
                therionModule.setTherionType(TherionModule.TSINGLUNG);
                therionModule.setId(therionboss.getId());
                therionModule.setName(therionboss.getName());
                therionModule.setLife(therionboss.getLife());
                therionModule.setTotalLife(therionboss.getLife());
                therionModule.setStatus(2); //已重生
                therionModule.setChallengeNum(0); //初始挑战人数为0
                therionModule.setRebirthtime(therionboss.getRebirthtime()); //刷新时长
                therionModule.setResurrectTime(null); //重生倒计时时间  死亡时间 + 复活冷却时间  初始值为空
                therionModule.setRewardtype(therionboss.getRewardtype());
                therionModule.setRewardid(therionboss.getRewardid());
                therionModule.setRewardnumber(therionboss.getRewardnumber());

                therionModule.setConditions(therionModelInfo.getCondition()); //关卡开放时间,每周的第几天

                map.put(TherionModule.TSINGLUNG, therionModule); //青龙
            }
            if (code == 2 && therionboss.getType() == type) {
                therionModule.setTherionType(TherionModule.WHITETIGER);
                therionModule.setId(therionboss.getId());
                therionModule.setName(therionboss.getName());
                therionModule.setLife(therionboss.getLife());
                therionModule.setTotalLife(therionboss.getLife());
                therionModule.setStatus(2); //已重生
                therionModule.setChallengeNum(0); //初始挑战人数为0
                therionModule.setRebirthtime(therionboss.getRebirthtime()); //刷新时长
                therionModule.setResurrectTime(null); //重生倒计时时间  死亡时间 + 复活冷却时间  初始值为空
                therionModule.setRewardtype(therionboss.getRewardtype());
                therionModule.setRewardid(therionboss.getRewardid());
                therionModule.setRewardnumber(therionboss.getRewardnumber());

                therionModule.setConditions(therionModelInfo.getCondition()); //关卡开放时间,每周的第几天

                map.put(TherionModule.WHITETIGER, therionModule); //白虎
            }
            if (code == 3 && therionboss.getType() == type) {
                therionModule.setTherionType(TherionModule.ROSEFINCH);
                therionModule.setId(therionboss.getId());
                therionModule.setName(therionboss.getName());
                therionModule.setLife(therionboss.getLife());
                therionModule.setTotalLife(therionboss.getLife());
                therionModule.setStatus(2); //已重生
                therionModule.setChallengeNum(0); //初始挑战人数为0
                therionModule.setRebirthtime(therionboss.getRebirthtime()); //刷新时长
                therionModule.setResurrectTime(null); //重生倒计时时间  死亡时间 + 复活冷却时间  初始值为空
                therionModule.setRewardtype(therionboss.getRewardtype());
                therionModule.setRewardid(therionboss.getRewardid());
                therionModule.setRewardnumber(therionboss.getRewardnumber());

                therionModule.setConditions(therionModelInfo.getCondition()); //关卡开放时间,每周的第几天

                map.put(TherionModule.ROSEFINCH, therionModule); //朱雀
            }
            if (code == 0 && therionboss.getType() == type) {
                therionModule.setTherionType(TherionModule.BASALTIC);
                therionModule.setId(therionboss.getId());
                therionModule.setName(therionboss.getName());
                therionModule.setLife(therionboss.getLife());
                therionModule.setTotalLife(therionboss.getLife());
                therionModule.setStatus(2); //已重生
                therionModule.setChallengeNum(0); //初始挑战人数为0
                therionModule.setRebirthtime(therionboss.getRebirthtime()); //刷新时长
                therionModule.setResurrectTime(null); //重生倒计时时间  死亡时间 + 复活冷却时间  初始值为空
                therionModule.setRewardtype(therionboss.getRewardtype());
                therionModule.setRewardid(therionboss.getRewardid());
                therionModule.setRewardnumber(therionboss.getRewardnumber());

                therionModule.setConditions(therionModelInfo.getCondition()); //关卡开放时间,每周的第几天

                map.put(TherionModule.BASALTIC, therionModule); //玄武
            }
        }

    }

    /**
     * 神兽玩法UI界面  初始化的开启时间、结束时间、重生时间为空
     *
     * @param module
     * @param type   玩法类型
     * @param key    神兽类型
     */
    public void mainUI(String playerCode, TherionModule module, int type, Integer key) {
        //玩法已开启
        if (module.isOpen()) {
            //更新挑战位上的人数
            Map<Integer, TherionChallengingPosition> positionMap = TherionChallengingPosition.getAll(type, playerCode, key);
            int challengeNum = 0;
            for (TherionChallengingPosition position : positionMap.values()) {
                if (position != null && position.getPlayCode() != null) {
                    challengeNum++;
                }
            }
            module.setChallengeNum(challengeNum);
            module.set(type, key, playerCode);
            return;
        }
    }


    public static void clearRandkAndInfo(int  serverId, int gameType, int therionType) {
        int areaIdOrGroupId = 0;
        switch (gameType) {
            case TherionModule.THERION_LOCAL://本服
                areaIdOrGroupId = serverId;
                break;
            case TherionModule.THERION_CROSS://跨服
                AreaBean areaBean = AreaBean.get(serverId);
                areaIdOrGroupId = areaBean.getGroupId();
                break;
            case TherionModule.THERION_WORLD://世界
                areaBean = AreaBean.get(serverId);
                areaIdOrGroupId = areaBean.getGroupId();
                break;
        }

        //挑战位清空
        TherionChallengingPosition.removeAllFromRedis(gameType, areaIdOrGroupId, therionType);
        RankModule rankModule = TherionFutureHandle.getRankModule(gameType, areaIdOrGroupId, therionType);
        //排行榜清空
        rankModule.clear();
    }


    /**
     * 封装神兽玩法的神兽信息  神兽入口
     *
     * @param module
     * @return
     */
    public TherionHuntingMessage.Therion.Builder packTherionModule(TherionModule module) {
        TherionHuntingMessage.Therion.Builder therion = TherionHuntingMessage.Therion.newBuilder();

        therion.setId(module.getId());
        therion.setName(module.getName());
        therion.setLife(module.getLife());
        therion.setTotalLife(module.getTotalLife());
        therion.setStatus(module.getStatus());
        therion.addAllCondition(Arrays.stream(module.getConditions()).boxed().collect(Collectors.toList()));
        //玩法开启
        if (module.isOpen() && module.isOpen()) {
            therion.setOpenTime(module.getOpenTime().getMillis());
            therion.setEndTime(module.getEndTime().getMillis());
        }
        //神兽复活中
        if (module.getResurrectTime() != null) {
            therion.setResurrectTime(module.getResurrectTime().getMillis());
        }
        therion.setChallengeNum(module.getChallengeNum());

        return therion;
    }

    /**
     * 神兽战斗界面信息处理
     *
     * @param playerCode
     * @param gameType
     * @param therionType
     * @param therionModule
     * @param positionMap
     * @return
     */
    public Result handleTherionModule(String playerCode, int gameType, int therionType, TherionModule therionModule, Map<Integer, TherionChallengingPosition> positionMap) {
        //查询所有非空挑战位上对神兽的总伤害
        long positionTotalDamage = 0;
        for (TherionChallengingPosition position : positionMap.values()) {
            if (position.getPlayCode() != null) {
                long damage = calculateDamage(position.getPlayCode(), gameType, therionType);
                positionTotalDamage += damage;
            }
        }


        //根据伤害减少神兽血量
        if (positionTotalDamage > therionModule.getLife()) {
            //当前的那只神兽信息
            therionboss boss = DataCenter.getData(therionModule.getId(), therionboss.class);
            String[] hours = boss.getSpawntime().split(",");

            //神兽死亡
            therionModule.setLife(0);
            therionModule.setStatus(3); //复活中
            therionModule.setOpen(false);
            TherionHandle.setTherionModuleResurrectTime(hours, therionModule, gameType, boss);//重生倒计时//重生倒计时
            therionModule.set(gameType, therionType, playerCode);
            therionModule.setNeedSettle(true);
        } else {
            therionModule.setLife(therionModule.getLife() - positionTotalDamage);
        }
        therionModule.set(gameType, therionType, playerCode);

        return Result.Success;
    }

    /**
     * 模式信息封装
     *
     * @param modelInfos
     * @param response
     * @return
     */
    public Result packModelInfo(ArrayList<TherionModelInfo> modelInfos, TherionHuntingMessage.TherionPlayModeChooseResponse.Builder response) {
        DateTime now = DateTime.now();

        for (TherionModelInfo modelInfo : modelInfos) {
            TherionHuntingMessage.TherionModelInfo.Builder therionModelInfo = TherionHuntingMessage.TherionModelInfo.newBuilder();
            //奖励封装
            theriondate data = DataCenter.getData(modelInfo.getId(), theriondate.class);
            Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
            therionModelInfo.addAllItem(new CurrencyHandle().packItems(rewards));

            int[] condition = modelInfo.getCondition(); //关卡开放的时间，每周的哪一天

            if (ArrayUtils.contains(condition, 0)) { //本服每天开放
                therionModelInfo.setIsOpen(true);
            } else {
                therionModelInfo.setIsOpen(ArrayUtils.contains(condition, now.getDayOfWeek())); //关卡开启
            }


            response.addTherionModelInfo(therionModelInfo);
        }
        return Result.Success;
    }

    /**
     * 通过神兽ID，获取神兽的Key
     *
     * @param therionId
     * @return
     */
    public static int getTherionKey(int therionId) {
        int i = therionId % 4;
        if (i == 1) {
            return TherionModule.TSINGLUNG;
        } else if (i == 2) {
            return TherionModule.WHITETIGER;
        } else if (i == 3) {
            return TherionModule.ROSEFINCH;
        } else if (i == 0) {
            return TherionModule.BASALTIC;
        }
        return -1;
    }

    /**
     * 封装排行榜信息
     *
     * @param playerCode
     * @param top        前50名
     * @param rank       排行榜
     * @param response
     */
    public void packRank(String playerCode, Collection<RankEntry> top, RankModule rank, TherionHuntingMessage.TherionHuntingRankResponse.Builder response) {
        PlayerHandle playerHandle = new PlayerHandle();

        int ranking = 0;
        for (RankEntry entry : top) {
            String pCode = entry.getKey();
            int score = entry.getValue().intValue(); //总伤害数值

            TherionHuntingMessage.RankInfo.Builder builder = TherionHuntingMessage.RankInfo.newBuilder();
            builder.setRank(++ranking);
            builder.setPlayer(playerHandle.playerSimpleInfo(pCode));
            builder.setTotalValue(score);
            response.addRankInfos(builder);
        }

        {
            int playerRank = 0;
            int score = 0;
            RankEntry entry = rank.get(playerCode);
            if (entry != null) {
                playerRank = rank.rank(playerCode);
                score = entry.getValue().intValue();
            }
            TherionHuntingMessage.RankInfo.Builder builder = TherionHuntingMessage.RankInfo.newBuilder();
            builder.setRank(playerRank);
            builder.setPlayer(playerHandle.playerSimpleInfo(playerCode));
            builder.setTotalValue(score);
            response.setMyRank(builder);
        }

    }

    /**
     * 封装挑战记录信息
     *
     * @param map
     * @param response
     */
    public void packRecords(HashMap<Integer, TherionChallengeRecord> map, TherionHuntingMessage.TherionChallengeRecordResponse.Builder response) {
        for (Integer therionType : map.keySet()) {
            TherionHuntingMessage.RecordInfo.Builder builder = TherionHuntingMessage.RecordInfo.newBuilder();
            TherionChallengeRecord therionChallengeRecord = map.get(therionType);
            if (therionChallengeRecord != null) {
                builder.setTherionId(therionChallengeRecord.getTheronId());
                builder.setTherionName(therionChallengeRecord.getTherionName());
                builder.setDate(therionChallengeRecord.getDate().getMillis());
                builder.setRank(therionChallengeRecord.getRank());
                builder.setTotalValue(therionChallengeRecord.getTotalValue());
            }
            response.addRankInfo(builder);
        }
    }

    /**
     * 初始化挑战次数
     *
     * @param challengeNumMap
     * @return
     */
    public HashMap<Integer, Integer> initChallengeNum(HashMap<Integer, Integer> challengeNumMap) {
        HashMap<Integer, Integer> numMap = new HashMap<>();
        //每个神兽的挑战次数初始值为 2
        numMap.put(TherionModule.THERION_LOCAL, 2);
        numMap.put(TherionModule.THERION_CROSS, 2);
        numMap.put(TherionModule.THERION_WORLD, 1);

        return numMap;
    }

    /**
     * 封装神兽挑战UI信息,战斗界面
     *
     * @param playerCode
     * @param therionModule 神兽信息
     * @param positionMap   挑战位集合
     * @param rankModule    排名信息
     * @param response
     */
    public Result packTherionBattleUiInfo(String playerCode, TherionModule therionModule, Map<Integer, TherionChallengingPosition> positionMap, RankModule rankModule, TherionHuntingMessage.TherionHuntingBattleResponse.Builder response) {
        if (rankModule == null) {
            return Result.DataError;
        }

        PlayerHandle playerHandle = new PlayerHandle();

        //挑战神兽的信息
        TherionHuntingMessage.Therion.Builder therionBuilder = packTherionModule(therionModule);
        response.setTherion(therionBuilder);

        //所有挑战位信息
        for (TherionChallengingPosition position : positionMap.values()) {
            TherionHuntingMessage.ChallengePosition.Builder positionBuilder = TherionHuntingMessage.ChallengePosition.newBuilder();
            positionBuilder.setPosition(position.getPosition());

            int rank = 0; //排名
            long value = 0; //伤害

            String playCode = position.getPlayCode();
            if (playCode == null) { //挑战位是否空闲
                positionBuilder.setIsFree(true);
            } else {
                positionBuilder.setIsFree(false);

                therionboss therionboss = DataCenter.getData(therionBuilder.getId(), therionboss.class);
                //神兽有狂暴状态
                if (therionboss.getFinallylife() != -1) {
                    //在挑战位上；神兽血量大于40%
                    //不在挑战位上不能撤退
                    response.setCanRetreat(position.getPlayCode().equals(playCode) && therionBuilder.getLife() > therionboss.getFinallylife()); //能否撤退
                } else { //神兽无狂暴状态
                    response.setCanRetreat(position.getPlayCode().equals(playCode));
                }

                //挑战位上玩家信息
                PlayerMessage.PlayerSimpleInfo.Builder playerInfo = playerHandle.playerSimpleInfo(position.getPlayCode());
                positionBuilder.setPlayInfo(playerInfo);
                //战位上玩家排名
                RankEntry entry = rankModule.get(position.getPlayCode());
                if (entry != null) {
                    rank = rankModule.rank(position.getPlayCode());
                    value = entry.getValue();
                }
                positionBuilder.setRank(rank); //排名
                positionBuilder.setTotalValue(value);//伤害.
                response.addPositions(positionBuilder);
            }
        }

        //个人当前排名
        {
            TherionHuntingMessage.RankInfo.Builder rankIndoBuilder = TherionHuntingMessage.RankInfo.newBuilder();
            int rank = 0; //排名
            int score = 0; //伤害值
            RankEntry entry = rankModule.get(playerCode);
            if (entry != null) {
                rank = rankModule.rank(playerCode);
                score = entry.getValue().intValue();
            }
            rankIndoBuilder.setRank(rank);
            rankIndoBuilder.setTotalValue(score);
            PlayerMessage.PlayerSimpleInfo.Builder playerInfo = playerHandle.playerSimpleInfo(playerCode);
            rankIndoBuilder.setPlayer(playerInfo);
            response.setMyRank(rankIndoBuilder);
        }

        //挑战次数
        TherionPlayerModule playerModule = TherionPlayerModule.get(playerCode);
        if (playerModule != null) {
            Integer challengeNum = playerModule.getChallengeNum().get(therionModule.getGemeType());
            response.setChallengeNum(challengeNum);
        }
        return Result.Success;
    }

    public Result packTherionBattleUiInfo(String playerCode, TherionModule therionModule, Map<Integer, TherionChallengingPosition> positionMap, RankModule rankModule, TherionHuntingMessage.TherionHuntingPositionResponse.Builder response) {
        if (rankModule == null) {
            return Result.DataError;
        }

        PlayerHandle playerHandle = new PlayerHandle();

        TherionHuntingMessage.Therion.Builder therionBuilder = packTherionModule(therionModule);
        response.setTherion(therionBuilder);

        //所有挑战位信息
        for (TherionChallengingPosition position : positionMap.values()) {
            TherionHuntingMessage.ChallengePosition.Builder positionBuilder = TherionHuntingMessage.ChallengePosition.newBuilder();
            positionBuilder.setPosition(position.getPosition());

            int rank = 0; //排名

            String playCode = position.getPlayCode();
            if (playCode == null) { //挑战位是否空闲
                positionBuilder.setIsFree(true);
            } else {
                positionBuilder.setIsFree(false);

                therionboss therionboss = DataCenter.getData(therionBuilder.getId(), therionboss.class);
                //神兽有狂暴状态
                if (therionboss.getFinallylife() != -1) {
                    //在挑战位上；神兽血量大于40%
                    //不在挑战位上不能撤退
                    response.setCanRetreat(position.getPlayCode().equals(playCode) && therionBuilder.getLife() > therionboss.getFinallylife()); //能否撤退
                } else { //神兽无狂暴状态
                    response.setCanRetreat(position.getPlayCode().equals(playCode));
                }

                //挑战位上玩家信息
                PlayerMessage.PlayerSimpleInfo.Builder playerInfo = playerHandle.playerSimpleInfo(position.getPlayCode());
                positionBuilder.setPlayInfo(playerInfo);
                //战位上玩家排名
                RankEntry entry = rankModule.get(position.getPlayCode());
                if (entry != null) {
                    rank = rankModule.rank(position.getPlayCode());
                }
                positionBuilder.setRank(rank); //排名
                response.addPositions(positionBuilder);
            }
        }

        //个人当前排名
        {
            TherionHuntingMessage.RankInfo.Builder rankIndoBuilder = TherionHuntingMessage.RankInfo.newBuilder();
            int rank = 0; //排名
            int score = 0; //伤害值
            RankEntry entry = rankModule.get(playerCode);
            if (entry != null) {
                rank = rankModule.rank(playerCode);
                score = entry.getValue().intValue();
            }
            rankIndoBuilder.setRank(rank);
            rankIndoBuilder.setTotalValue(score);
            PlayerMessage.PlayerSimpleInfo.Builder playerInfo = playerHandle.playerSimpleInfo(playerCode);
            rankIndoBuilder.setPlayer(playerInfo);
            response.setMyRank(rankIndoBuilder);
        }

        return Result.Success;
    }

    public Result packTherionBattleUiInfo(String playerCode, TherionModule therionModule, Map<Integer, TherionChallengingPosition> positionMap, RankModule rankModule, TherionHuntingMessage.TherionHuntingRetreatResponse.Builder response) {
        if (rankModule == null) {
            return Result.DataError;
        }

        PlayerHandle playerHandle = new PlayerHandle();

        TherionHuntingMessage.Therion.Builder therionBuilder = packTherionModule(therionModule);
        response.setTherion(therionBuilder);

        //所有挑战位信息
        for (TherionChallengingPosition position : positionMap.values()) {
            TherionHuntingMessage.ChallengePosition.Builder positionBuilder = TherionHuntingMessage.ChallengePosition.newBuilder();
            positionBuilder.setPosition(position.getPosition());

            int rank = 0; //排名

            String playCode = position.getPlayCode();
            if (playCode == null) { //挑战位是否空闲
                positionBuilder.setIsFree(true);
            } else {
                positionBuilder.setIsFree(false);

                therionboss therionboss = DataCenter.getData(therionBuilder.getId(), therionboss.class);
                //神兽有狂暴状态
                if (therionboss.getFinallylife() != -1) {
                    //在挑战位上；神兽血量大于40%
                    //不在挑战位上不能撤退
                    response.setCanRetreat(position.getPlayCode().equals(playCode) && therionBuilder.getLife() > therionboss.getFinallylife()); //能否撤退
                } else { //神兽无狂暴状态
                    response.setCanRetreat(position.getPlayCode().equals(playCode));
                }

                //挑战位上玩家信息
                PlayerMessage.PlayerSimpleInfo.Builder playerInfo = playerHandle.playerSimpleInfo(position.getPlayCode());
                positionBuilder.setPlayInfo(playerInfo);
                //战位上玩家排名
                RankEntry entry = rankModule.get(position.getPlayCode());
                if (entry != null) {
                    rank = rankModule.rank(position.getPlayCode());
                }
                positionBuilder.setRank(rank); //排名
                response.addPositions(positionBuilder);
            }
        }

        //个人当前排名
        {
            TherionHuntingMessage.RankInfo.Builder rankIndoBuilder = TherionHuntingMessage.RankInfo.newBuilder();
            int rank = 0; //排名
            int score = 0; //伤害值
            RankEntry entry = rankModule.get(playerCode);
            if (entry != null) {
                rank = rankModule.rank(playerCode);
                score = entry.getValue().intValue();
            }
            rankIndoBuilder.setRank(rank);
            rankIndoBuilder.setTotalValue(score);
            PlayerMessage.PlayerSimpleInfo.Builder playerInfo = playerHandle.playerSimpleInfo(playerCode);
            rankIndoBuilder.setPlayer(playerInfo);
            response.setMyRank(rankIndoBuilder);
        }

        return Result.Success;
    }

    /**
     * 计算玩家对神兽的总伤害值
     *
     * @param playerCode
     * @param gameType   玩法类型
     * @param key        神兽Key
     */
    public static long calculateDamage(String playerCode, int gameType, int key) {
        TherionModule therionModule = TherionModule.get(gameType, playerCode, key);

        Map<Integer, TherionChallengingPosition> positionMap = TherionChallengingPosition.getAll(gameType, playerCode, key);
        TherionChallengingPosition position = null; //玩家所在挑战位

        int playerNum = 0; //挑战人数，多于一人触发神兽减伤
        for (TherionChallengingPosition challengingPosition : positionMap.values()) {
            if (challengingPosition.getPlayCode() != null) {
                playerNum++;
            }
            if (challengingPosition != null && challengingPosition.getPlayCode() != null && challengingPosition.getPlayCode().equals(playerCode)) {
                position = challengingPosition;
            }
        }

        int resistance = 0; //减伤值, -1没有减伤值
        if (playerNum > 1 && therionModule != null) {
            therionboss therionboss = DataCenter.getData(therionModule.getId(), therionboss.class);
            resistance = therionboss.getResistance()[playerNum - 2];
        } else {
            resistance = -1;
        }

        PlayerBean playerBean = PlayerBean.get(playerCode);
        long damage = playerBean.getPower() / 1000; //单次对神兽的伤害值：当前战力值/1000

        long totalDamage = 0; //总伤害值
        if (position != null && playerNum > 0) {
            //计算对神兽的伤害
            int time = (int) (DateTime.now().getMillis() - position.getTime().getMillis()) / 1000 / 3; //攻击次数
            if (resistance != -1) { //神兽减伤
                if (time == 0) {  //每三秒请求一次，不足的按一次算
                    totalDamage = new Double(damage * (resistance / 10000.0)).longValue();
                } else {
                    totalDamage = new Double(damage * (resistance / 10000.0) * time).longValue(); //总伤害值 = 减伤后伤害值 * 攻击次数
                }
            }

            if (resistance == -1) {
                //没有减伤
                if (time == 0) {  //每三秒请求一次，不足的按一次算
                    totalDamage = damage;
                } else {
                    totalDamage = damage * time; //总伤害值 = 减伤后伤害值 * 攻击次数
                }
            }
        }

        //上传排行榜
        addValue(therionModule, gameType, playerCode, totalDamage);

        //伤害计算完毕，重置时间
        if (position != null) {
            position.setTime(DateTime.now());
            position.set(gameType, playerCode, therionModule.getTherionType(), position.getPosition());
        }

        return totalDamage;
    }


    /**
     * 上传排行榜
     *
     * @param therionModule    神兽
     * @param gameType         玩法类型
     * @param playerCode       用户id
     * @param finalTotalDamage 伤害值
     */
    public static void addValue(TherionModule therionModule, int gameType, String playerCode, long finalTotalDamage) {
        //上传排行榜
        int therionKey = therionModule.getTherionType();
        switch (gameType) {
            case TherionModule.THERION_LOCAL:
                RankModule areaRank = AreaRankTherionChallege.getRank(playerCode, therionKey);
                areaRank.addAndSet(playerCode,finalTotalDamage);
                break;
            case TherionModule.THERION_CROSS:
                RankModule AreaGroup = AreaGroupRankTherionChallege.getRank(playerCode, therionKey);
                AreaGroup.addAndSet(playerCode,finalTotalDamage);
                break;
            case TherionModule.THERION_WORLD:
                RankModule WorldRank = WorldRankTherionChallege.getRank(playerCode, therionKey);
                WorldRank.addAndSet(playerCode,finalTotalDamage);
                break;
        }
    }


    /**
     * 玩家争夺挑战位
     *
     * @param playerCode
     * @param oppoCode     对手的playCode
     * @param gameType     玩法类型
     * @param therionKey   神兽Key
     * @param response
     * @param playerModule
     * @param handle
     * @return
     */
    public Result battleExecute(String playerCode, String oppoCode, int gameType, int therionKey, TherionHuntingMessage.TherionHuntingPositionChallengeResponse.Builder response, TherionPlayerModule playerModule, TherionHandle handle) {
        TherionPlayerModule therionPlayerModuleA = TherionPlayerModule.get(playerCode);
        TherionPlayerModule therionPlayerModuleB = TherionPlayerModule.get(oppoCode);

        BattleHandle battleHandle = new BattleHandle();

        BattleModule battleModule = BattleModule.create(playerCode);
        battleModule.setType(BattleType.THERION);
        battleModule.setCode(BattleType.THERION.name());

        // 玩家的team
        TeamModule teamA = battleHandle.teamPlayer(playerCode, Format.FormatType.普通);
        battleModule.setTeamA(teamA);

        // 玩家的team
        TeamModule teamB = battleHandle.teamPlayer(oppoCode, Format.FormatType.普通);
        battleModule.setTeamB(teamB);

        Team team_a = teamA.team(true);
        Team team_b = teamB.team(false);
        team_a.setTeam对手(team_b);
        team_b.setTeam对手(team_a);

        // 处理战斗
        battleHandle.battleExecute(battleModule, team_a, team_b, 20);
        boolean isWin = battleModule.getBattleResult().equals(BattleResult.LEFT_WIN);

        // 根据挑战结果处理

        if (isWin) {
            // 挑战位更新
            Map<Integer, TherionChallengingPosition> positionMap = TherionChallengingPosition.getAll(gameType, oppoCode, therionKey);
            for (TherionChallengingPosition position : positionMap.values()) {
                //todo 加锁改变位置状态和用户挑战次数
                try {
                    if (TherionChallengingPosition.lockTherionChallengingPosition(gameType, playerCode, therionKey)) {
                        //撤出原来的挑战位
                        if (position != null && position.getPlayCode() != null && position.getPlayCode().equals(playerCode)) {
                            position.setPlayCode(null);
                            position.setTime(null);
                            position.setOccupyTime(null);
                            position.set(gameType, playerCode, therionKey, position.getPosition());
                        }
                        //占领新的挑战位
                        if (position != null && position.getPlayCode() != null && position.getPlayCode().equals(oppoCode)) {
                            //给原本的玩家发提示
                            PlayerBean bean = PlayerBean.get(playerCode);
                            new NotificationHandle().notifyTherionDefeat(playerCode, oppoCode, TherionModule.getName(therionKey), bean.getName(), gameType);

                            position.setPlayCode(playerCode);
                            position.setTime(DateTime.now());
                            position.setOccupyTime(DateTime.now());
                            position.set(gameType, oppoCode, therionKey, position.getPosition());
                        }

                        //排行榜上没有玩家信息，挑战次数 - 1
                        Integer num = playerModule.getChallengeNum().get(gameType);//挑战次数
                        boolean inRank = handle.isInRank(gameType, playerCode, therionKey);
                        if (!inRank && num > 0) {
                            //给玩家计算伤害，避免抢位置太快，造成的伤害都判断为空，次数多扣
                            TherionModule therionModule = TherionModule.get(gameType, playerCode, therionKey);
                            TherionHandle.addValue(therionModule, gameType, playerCode, 1);
                            playerModule.getChallengeNum().put(gameType, num - 1);
                            playerModule.set(playerCode);
                        }

                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    TherionChallengingPosition.unlockTherionChallengingPosition(gameType, playerCode, therionKey);
                }
            }
        } else {
            //挑战失败，10秒内无法挑战同一玩家
            TherionPlayerModule oppoPlayerModule = TherionPlayerModule.get(oppoCode);
            if (oppoPlayerModule == null) {
                return Result.DataError;
            }
            HashMap<String, DateTime> challengeCoolDownMap = oppoPlayerModule.getCoolDown().get(gameType);
            challengeCoolDownMap.put(playerCode, DateTime.now()); //记录当前挑战时间
            oppoPlayerModule.set(oppoCode);
        }


        //处理录像
        {
            BattleRecord battleRecord = battleModule.saveRecord(BattleRecord.randomCode(), 1);
            TherionModule therionModule = TherionModule.get(gameType, playerCode, therionKey);

            TherionRecord therionRecord = new TherionRecord();
            therionRecord.setTherionId(therionModule.getId()); //神兽ID
            therionRecord.setAttackerCode(playerCode);
            therionRecord.setDefenderCode(oppoCode);
            therionRecord.setDate(DateTime.now());
            therionRecord.setBattleResult(battleModule.getBattleResult());
            therionRecord.setRecordCode(battleRecord.getCode());
            if (therionPlayerModuleA != null) {
                TherionRecord.add(playerCode, therionRecord);
            }
            if (therionPlayerModuleB != null) {
                TherionRecord.add(oppoCode, therionRecord);
            }
        }

        //封装消息
        {
            TherionHuntingMessage.TherionFighter.Builder fighterA = packFighter(playerCode);
            TherionHuntingMessage.TherionFighter.Builder fighterB = packFighter(oppoCode);

            BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();
            builder.setPlayback(battleHandle.playback(battleModule));

            response.setBattleResp(builder);//录像
            response.setBattleResult(battleModule.getBattleResult().getNumber());// 战果

            response.setFighterA(fighterA);// 进攻方
            response.setFighterB(fighterB);// 防守方
        }

        return Result.Success;
    }


    /**
     * 战斗玩家信息封装
     *
     * @param playerCode
     * @return
     */
    public TherionHuntingMessage.TherionFighter.Builder packFighter(String playerCode) {
        TherionHuntingMessage.TherionFighter.Builder builder = TherionHuntingMessage.TherionFighter.newBuilder();
        PlayerBean player = PlayerBean.get(playerCode);
        builder.setPlayerCode(player.getCode());
        builder.setNickname(player.getName());
        builder.setHead(player.getHead());
        builder.setHeadFrame(player.getHeadframe());
        builder.setLevel(player.getLevel());
        return builder;
    }

    /**
     * 获取某个排行榜（本服、跨服、世界）
     *
     * @param gameType
     * @param playerCode
     * @param therionType
     */
    public RankModule getRankModule(int gameType, String playerCode, int therionType) {
        switch (gameType) {
            case TherionModule.THERION_LOCAL:
                return AreaRankTherionChallege.getRank(playerCode, therionType);
            case TherionModule.THERION_CROSS:
                return AreaGroupRankTherionChallege.getRank(playerCode, therionType);
            case TherionModule.THERION_WORLD:
                return WorldRankTherionChallege.getRank(playerCode, therionType);
            default:
                return null;
        }
    }

    /**
     * 玩家撤退处理
     *
     * @param gameType
     * @param playerCode
     * @param therionType
     * @param initialLife   神兽初始血量
     * @param therionModule
     * @param rankModule
     * @param positionId    撤退的挑战位
     * @return
     */
    public Result retreatHandle(int gameType, String playerCode, int therionType, long initialLife, TherionModule therionModule, RankModule rankModule, int positionId) {

        TherionChallengingPosition position = TherionChallengingPosition.get(gameType, playerCode, therionType, positionId);//位置信息
        //查询排行榜上是否有该玩家信息
        boolean inRank = isInRank(gameType, playerCode, therionType);

        if (position == null && !inRank) { //没有挑战过
            return Result.Success;
        }

        //有该玩家信息，返回一次挑战次数
        TherionPlayerModule playerModule = TherionPlayerModule.get(playerCode);
        if ((inRank || position.getPlayCode().equals(playerCode)) && playerModule != null) {
            Integer challengeNum = playerModule.getChallengeNum().get(gameType);
            if (challengeNum >= 0 && challengeNum < 2) {
                playerModule.getChallengeNum().put(gameType, challengeNum + 1); //挑战次数 + 1
            } else {
                playerModule.getChallengeNum().put(gameType, 2);
            }
            playerModule.set(playerCode);
        }


        //todo 1、计算玩家对神兽的伤害，清空玩家的排行和伤害
        long damage = 0; //伤害值
        RankEntry rankEntry = rankModule.get(playerCode);
        if (rankEntry != null) {
            damage = rankEntry.getValue();
            rankModule.remove(playerCode); //清空排行
        }

        //todo 2、为神兽回复等量生命值
        long life = therionModule.getLife(); //神兽当前生命值
        if (life < initialLife) {
            therionModule.setLife(therionModule.getLife() + damage); //回复伤害值等量生命
            if (therionModule.getLife() > initialLife) {
                //回复后的生命值大于初始生命值,重置为初始生命值
                therionModule.setLife(initialLife);
            }
            therionModule.set(gameType, therionType, playerCode);
        }

        //todo 3、玩家所占的挑战位 置空
        if (position != null && position.getPlayCode().equals(playerCode)) {
            position.setPlayCode(null);
            position.setOccupyTime(null);
            position.set(gameType, playerCode, therionType, positionId);
        }

        return Result.Success;
    }

    /**
     * 初始化 神兽复活信息是否订阅
     *
     * @param map
     * @return
     */
    public HashMap<Integer, HashMap<Integer, Integer>> initIsbooked(HashMap<Integer, HashMap<Integer, Integer>> map) {
        HashMap<Integer, Integer> bookedMap1 = new HashMap<>();
        HashMap<Integer, Integer> bookedMap2 = new HashMap<>();
        HashMap<Integer, Integer> bookedMap3 = new HashMap<>();
        //默认每个神兽的复活信息 不订阅
        bookedMap1.put(TherionModule.TSINGLUNG, 0);
        bookedMap1.put(TherionModule.WHITETIGER, 0);
        bookedMap1.put(TherionModule.ROSEFINCH, 0);
        bookedMap1.put(TherionModule.BASALTIC, 0);

        bookedMap2.put(TherionModule.TSINGLUNG, 0);
        bookedMap2.put(TherionModule.WHITETIGER, 0);
        bookedMap2.put(TherionModule.ROSEFINCH, 0);
        bookedMap2.put(TherionModule.BASALTIC, 0);

        bookedMap3.put(TherionModule.TSINGLUNG, 0);
        bookedMap3.put(TherionModule.WHITETIGER, 0);
        bookedMap3.put(TherionModule.ROSEFINCH, 0);
        bookedMap3.put(TherionModule.BASALTIC, 0);

        map.put(TherionModule.THERION_LOCAL, bookedMap1); //本服
        map.put(TherionModule.THERION_CROSS, bookedMap2); //战区
        map.put(TherionModule.THERION_WORLD, bookedMap3); //跨服世界

        return map;
    }

    /**
     * 获取玩家挑战记录
     *
     * @param playerCode
     * @param response
     * @return
     */
    public Result record(String playerCode, TherionHuntingMessage.TherionPlayerChallengeRecordResponse.Builder response) {
        List<TherionRecord> recordList = TherionRecord.get(playerCode);
        for (TherionRecord record : recordList) {
            boolean isAttacker = record.getAttackerCode().equals(playerCode);

            TherionHuntingMessage.PlayerChallengeRecord.Builder builder = TherionHuntingMessage.PlayerChallengeRecord.newBuilder();
            builder.setAttack(isAttacker);
            builder.setRecord(record.getRecordCode());
            builder.setDate(record.getDate().getMillis());
            builder.setOppoInfo(oppoInfo(isAttacker ? record.getDefenderCode() : record.getAttackerCode()));
            builder.setResult(record.getBattleResult().getNumber());
            builder.setTherionId(record.getTherionId());
            response.addRecords(builder);
        }
        return Result.Success;
    }

    public PlayerMessage.PlayerSimpleInfo.Builder oppoInfo(String playerCode) {
        return new PlayerHandle().playerSimpleInfo(playerCode);
    }

    /**
     * 玩家预定神兽复活
     *
     * @param therionModule
     * @param isChecked
     * @return
     */
    public Result bookedTherion(TherionModule therionModule, boolean isChecked, String playerCode) {
        TherionPlayerModule playerModule = TherionPlayerModule.get(playerCode);
        if (playerModule == null) {
            return Result.DataError;
        }

        Integer isBooked = playerModule.getIsBooked().get(therionModule.getGemeType()).get(therionModule.getTherionType());
        if (isChecked && isBooked == 0) {
            playerModule.getIsBooked().get(therionModule.getGemeType()).put(therionModule.getTherionType(), 1);
        } else if (!isChecked && isBooked == 1) {
            playerModule.getIsBooked().get(therionModule.getGemeType()).put(therionModule.getTherionType(), 0);
        }
        playerModule.set(playerCode);

        return Result.Success;
    }

    /**
     * 查询排行榜上是否有该玩家信息
     *
     * @param gameType
     * @param playerCode
     * @param therionType
     * @return
     */
    public boolean isInRank(int gameType, String playerCode, int therionType) {
        boolean flag = false;
        switch (gameType) {
            case TherionModule.THERION_LOCAL:
                AreaRankTherionChallege areaRank = AreaRankTherionChallege.getRank(playerCode, therionType);//本服
                for (String key : areaRank.allKeys()) {
                    if (key.equals(playerCode)) {
                        flag = true; //排行榜上有玩家信息
                        break;
                    }
                }
                break;
            case TherionModule.THERION_CROSS:
                AreaGroupRankTherionChallege areaGroupRank = AreaGroupRankTherionChallege.getRank(playerCode, therionType);//跨服
                for (String key : areaGroupRank.allKeys()) {
                    if (key.equals(playerCode)) {
                        flag = true; //排行榜上有玩家信息
                        break;
                    }
                }
                break;
            case TherionModule.THERION_WORLD:
                WorldRankTherionChallege worldRank = WorldRankTherionChallege.getRank(playerCode, therionType);//世界
                for (String key : worldRank.allKeys()) {
                    if (key.equals(playerCode)) {
                        flag = true; //排行榜上有玩家信息
                        break;
                    }
                }
                break;
        }
        return flag;
    }

    /**
     * 初始化神兽玩法挑战记录
     *
     * @param map
     * @return
     */
    public HashMap<Integer, HashMap<Integer, TherionChallengeRecord>> initChallengeRecords(HashMap<Integer, HashMap<Integer, TherionChallengeRecord>> map) {
        map.put(TherionModule.THERION_LOCAL, new HashMap<Integer, TherionChallengeRecord>()); //本服
        map.put(TherionModule.THERION_CROSS, new HashMap<Integer, TherionChallengeRecord>()); //战区
        map.put(TherionModule.THERION_WORLD, new HashMap<Integer, TherionChallengeRecord>()); //跨服世界

        return map;
    }


    public static void setTherionModuleResurrectTime(String[] hours, TherionModule therionModule, int gameType, therionboss boss) {

        //todo 世界神兽10分钟刷新，其他按表整点刷新
        if (TherionModule.THERION_WORLD == gameType) {
            int rebirthtime = boss.getRebirthtime();
            therionModule.setResurrectTime(DateTime.now().plusSeconds(rebirthtime));//重生倒计时
            return;
        }


        //todo 跨服或本服的刷新规则
        Calendar calendar = Calendar.getInstance();
        int nowTime = calendar.get(Calendar.HOUR_OF_DAY) + 1;
        for (int i = hours.length - 1; i >= 0; i--) {
            //如果时间大于最后一个时间,则默认下次复活时间为表中的第一个时间
            if (nowTime > Integer.parseInt(hours[hours.length - 1])) {
                calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hours[0]));
                calendar.add(Calendar.DAY_OF_MONTH, 1);
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                Date time = calendar.getTime();
                therionModule.setResurrectTime(new DateTime(time));
                break;
            }

            //时间在第一个时间前，则默认下次复活时间为表中的第一个时间
            if (nowTime <= Integer.parseInt(hours[0])) {
                calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hours[0]));
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                Date time = calendar.getTime();
                therionModule.setResurrectTime(new DateTime(time));
                break;
            }

            if (nowTime > Integer.parseInt(hours[i])) {
                calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hours[i + 1]));
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                Date time = calendar.getTime();
                therionModule.setResurrectTime(new DateTime(time));
                break;
            }
        }

    }
}
